<style lang="scss" scoped>
.blog-container {
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}

.blog-layout {
  position: relative;
}

.blog-header-section {
  width: 100%;
}

.blog-sidebar-right {
  position: sticky;
  top: 20px; // 调整顶部位置，避免被header挡住
  max-height: calc(100vh - 104px);
  overflow-y: auto;
  padding-left: 20px; // 与主内容保持适当间距
}

.blog-header-card {
  margin-bottom: 0;
}

.blog-cover {
  position: relative;
}

.blog-cover-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(
    135deg,
    rgba(0, 0, 0, 0.4) 0%,
    rgba(0, 0, 0, 0.2) 50%,
    rgba(0, 0, 0, 0.6) 100%
  );
  display: flex;
  align-items: center;
  color: white;
}

.blog-title {
  font-weight: 700;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}

.blog-subtitle {
  opacity: 0.9;
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}

.blog-content-card {
  border-radius: 16px;
  overflow: hidden;
}

.blog-content {
  line-height: 1.8;
  font-size: 1.1rem;
  color: #333;

  :deep(h1),
  :deep(h2),
  :deep(h3),
  :deep(h4),
  :deep(h5),
  :deep(h6) {
    margin: 2rem 0 1rem 0;
    font-weight: 600;
    line-height: 1.3;
    color: #2c3e50;
    scroll-margin-top: 80px;
  }

  :deep(h1) {
    font-size: 2rem;
    border-bottom: 3px solid #1976d2;
    padding-bottom: 10px;
  }

  :deep(h2) {
    font-size: 1.6rem;
    border-bottom: 2px solid #e0e0e0;
    padding-bottom: 8px;
  }

  :deep(h3) {
    font-size: 1.3rem;
    color: #1976d2;
  }

  :deep(p) {
    margin: 1.2rem 0;
    text-align: justify;
  }

  :deep(blockquote) {
    border-left: 4px solid #1976d2;
    background: #f8f9fa;
    padding: 20px;
    margin: 20px 0;
    border-radius: 0 8px 8px 0;
    font-style: italic;
    position: relative;
  }

  :deep(blockquote::before) {
    content: '"';
    font-size: 4rem;
    color: #1976d2;
    position: absolute;
    top: -10px;
    left: 10px;
    opacity: 0.3;
  }

  :deep(code) {
    background: #f1f3f4;
    padding: 2px 6px;
    border-radius: 4px;
    font-family: 'Fira Code', 'Consolas', monospace;
    font-size: 0.9em;
    color: #e83e8c;
  }

  :deep(pre) {
    background: #2d3748;
    color: #e2e8f0;
    padding: 20px;
    border-radius: 8px;
    overflow-x: auto;
    margin: 20px 0;
    position: relative;
  }

  :deep(pre code) {
    background: none;
    padding: 0;
    color: inherit;
    font-size: 0.9rem;
  }

  :deep(ul),
  :deep(ol) {
    padding-left: 2rem;
    margin: 1rem 0;
  }

  :deep(li) {
    margin: 0.5rem 0;
  }

  :deep(table) {
    width: 100%;
    border-collapse: collapse;
    margin: 20px 0;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }

  :deep(th),
  :deep(td) {
    padding: 12px 16px;
    text-align: left;
    border-bottom: 1px solid #e0e0e0;
  }

  :deep(th) {
    background: #f8f9fa;
    font-weight: 600;
    color: #495057;
  }

  :deep(img) {
    max-width: 100%;
    height: auto;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    margin: 20px 0;
  }

  :deep(a) {
    color: #1976d2;
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: all 0.3s ease;
  }

  :deep(a:hover) {
    border-bottom-color: #1976d2;
  }

  :deep(hr) {
    border: none;
    height: 2px;
    background: linear-gradient(90deg, transparent, #1976d2, transparent);
    margin: 40px 0;
  }
}

.toc-list {
  .toc-item {
    border-radius: 8px;
    margin: 2px 0;
    transition: all 0.3s ease;

    &.active-toc {
      background-color: #e3f2fd;
      color: #1976d2;
    }

    &:hover {
      background-color: #f5f5f5;
    }
  }
}

.fab-button {
  position: fixed !important;
  bottom: 80px;
  right: 20px;
  z-index: 1000;
}

// 响应式设计
@media (max-width: 1024px) {
  .blog-layout {
    margin-top: 56px; // 移动端header高度
  }

  .blog-sidebar-right {
    position: static;
    max-height: none;
    margin-top: 20px;
  }
}

@media (max-width: 768px) {
  .blog-cover-overlay {
    padding: 20px;
  }

  .blog-title {
    font-size: 1.8rem !important;
  }

  .blog-subtitle {
    font-size: 1.1rem !important;
  }

  .blog-content {
    font-size: 1rem;

    :deep(h1) {
      font-size: 1.6rem;
    }

    :deep(h2) {
      font-size: 1.4rem;
    }

    :deep(h3) {
      font-size: 1.2rem;
    }
  }
}
</style>

<template>
  <v-main ref="blog-content" class="blog-container flex-fill overflow-y-auto">
    <!-- 阅读进度条 -->
    <v-progress-linear
      :model-value="readingProgress"
      color="primary"
      height="4"
      class="fixed-top"
      style="z-index: 1000"
    ></v-progress-linear>

    <!-- 主要内容区域 -->
    <div class="blog-layout">
      <!-- 博客头部 - 与内容等宽 -->
      <div class="blog-header-section">
        <v-img :src="blogData.coverImage" height="300" cover class="blog-cover">
          <div class="blog-cover-overlay">
            <v-container>
              <v-row justify="center">
                <v-col cols="12" md="10" lg="7" xl="6">
                  <h1 class="blog-title text-h3 text-center mb-4">
                    {{ blogData.title }}
                  </h1>
                  <p class="blog-subtitle text-h6 text-center mb-6">
                    {{ blogData.subtitle }}
                  </p>
                  <div class="d-flex justify-center flex-wrap gap-4">
                    <v-chip
                      v-for="meta in blogMeta"
                      :key="meta.text"
                      :prepend-icon="meta.icon"
                      size="large"
                      color="white"
                      variant="elevated"
                    >
                      {{ meta.text }}
                    </v-chip>
                  </div>
                </v-col>
              </v-row>
            </v-container>
          </div>
        </v-img>
      </div>

      <!-- 内容区域 -->
      <v-container class="py-8">
        <v-row justify="center">
          <!-- 主内容区域 -->
          <v-col cols="12" md="10" lg="7" xl="6" class="blog-main-content">
            <v-card elevation="2" class="blog-content-card">
              <v-card-text class="pa-8">
                <!-- 加载状态 -->
                <div v-if="loading" class="text-center py-12">
                  <v-progress-circular
                    indeterminate
                    color="primary"
                    size="64"
                  ></v-progress-circular>
                  <p class="mt-4 text-h6">加载中...</p>
                </div>

                <!-- 错误状态 -->
                <div v-else-if="error" class="text-center py-12">
                  <v-icon size="64" color="error">mdi-alert-circle</v-icon>
                  <p class="text-h6 mt-4">{{ error }}</p>
                  <v-btn color="primary" @click="loadBlog" class="mt-4"> 重试 </v-btn>
                </div>

                <!-- 博客内容 -->
                <div v-else class="blog-content" v-html="sanitizedContent"></div>
              </v-card-text>
            </v-card>

            <!-- 操作按钮 -->
            <div class="d-flex justify-space-between mt-6">
              <v-btn
                v-if="blogData.prevPost"
                :to="`/blog/${blogData.prevPost.id}`"
                prepend-icon="mdi-arrow-left"
                variant="outlined"
              >
                上一篇
              </v-btn>
              <v-spacer></v-spacer>
              <v-btn
                v-if="blogData.nextPost"
                :to="`/blog/${blogData.nextPost.id}`"
                append-icon="mdi-arrow-right"
                variant="outlined"
              >
                下一篇
              </v-btn>
            </div>

            <!-- 评论区域 -->
            <v-card class="mt-8" elevation="2">
              <v-card-title class="d-flex align-center">
                <v-icon class="mr-2">mdi-comment-text-multiple</v-icon>
                评论
              </v-card-title>
              <v-card-text>
                <!-- 评论列表 -->
                <v-list class="mt-6" v-if="comments.length > 0">
                  <v-list-item v-for="comment in comments" :key="comment.id" class="px-0">
                    <template v-slot:prepend>
                      <v-avatar color="primary" size="40">
                        <span class="text-white">{{ comment.name.charAt(0).toUpperCase() }}</span>
                      </v-avatar>
                    </template>
                    <v-list-item-title>{{ comment.name }}</v-list-item-title>
                    <v-list-item-subtitle>{{ formatDate(comment.createdAt) }}</v-list-item-subtitle>
                    <v-list-item-content class="mt-2">{{ comment.content }}</v-list-item-content>
                  </v-list-item>
                </v-list>
                <v-alert v-else type="info" class="mt-4">暂无评论，快来发表你的看法吧！</v-alert>
              </v-card-text>
            </v-card>
          </v-col>

          <!-- 右侧目录和信息 -->
          <v-col cols="12" md="10" lg="4" xl="3" v-if="showSidebar">
            <div class="blog-sidebar-right">
              <!-- 目录导航 -->
              <v-card class="mb-4" elevation="2">
                <v-card-title class="d-flex align-center">
                  <v-icon class="mr-2">mdi-format-list-bulleted</v-icon>
                  目录导航
                </v-card-title>
                <v-card-text class="pt-0">
                  <v-list density="compact" class="toc-list">
                    <v-list-item
                      v-for="heading in toc"
                      :key="heading.id"
                      :href="'#' + heading.id"
                      @click="scrollToHeading(heading.id)"
                      :class="{ 'active-toc': activeHeading === heading.id }"
                      class="toc-item"
                      :style="{ paddingLeft: (heading.level - 1) * 16 + 8 + 'px' }"
                    >
                      <v-list-item-title class="text-caption">
                        {{ heading.text }}
                      </v-list-item-title>
                    </v-list-item>
                  </v-list>
                </v-card-text>
              </v-card>

              <!-- 博客信息卡片 -->
              <v-card elevation="2">
                <v-card-title class="d-flex align-center">
                  <v-icon class="mr-2">mdi-information</v-icon>
                  博客信息
                </v-card-title>
                <v-card-text>
                  <v-list density="compact">
                    <v-list-item>
                      <template v-slot:prepend>
                        <v-icon size="small">mdi-account</v-icon>
                      </template>
                      <v-list-item-title>{{ blogData.author }}</v-list-item-title>
                    </v-list-item>
                    <v-list-item>
                      <template v-slot:prepend>
                        <v-icon size="small">mdi-calendar</v-icon>
                      </template>
                      <v-list-item-title>{{ formatDate(blogData.publishDate) }}</v-list-item-title>
                    </v-list-item>
                    <v-list-item>
                      <template v-slot:prepend>
                        <v-icon size="small">mdi-clock-outline</v-icon>
                      </template>
                      <v-list-item-title>{{ blogData.readTime }} 分钟阅读</v-list-item-title>
                    </v-list-item>
                    <v-list-item>
                      <template v-slot:prepend>
                        <v-icon size="small">mdi-eye</v-icon>
                      </template>
                      <v-list-item-title>{{ blogData.views }} 次浏览</v-list-item-title>
                    </v-list-item>
                  </v-list>

                  <!-- 标签 -->
                  <div class="mt-4">
                    <v-chip
                      v-for="tag in blogData.tags"
                      :key="tag"
                      size="small"
                      class="ma-1"
                      color="primary"
                      variant="outlined"
                    >
                      {{ tag }}
                    </v-chip>
                  </div>
                </v-card-text>
              </v-card>
            </div>
          </v-col>
        </v-row>
      </v-container>
    </div>

    <!-- 浮动操作按钮 -->
    <v-fab
      v-model="showFab"
      location="bottom end"
      size="large"
      color="primary"
      icon="mdi-arrow-up"
      @click="scrollToTop"
      class="fab-button"
    ></v-fab>

    <!-- 底部工具栏 -->
    <v-bottom-navigation v-model="bottomNav" color="primary" class="d-lg-none">
      <v-btn value="toc" @click="toggleSidebar">
        <v-icon>mdi-format-list-bulleted</v-icon>
        <span>目录</span>
      </v-btn>
      <v-btn value="share" @click="shareBlog">
        <v-icon>mdi-share</v-icon>
        <span>分享</span>
      </v-btn>
      <v-btn value="like" @click="toggleLike">
        <v-icon>{{ isLiked ? 'mdi-heart' : 'mdi-heart-outline' }}</v-icon>
        <span>{{ isLiked ? '已赞' : '点赞' }}</span>
      </v-btn>
    </v-bottom-navigation>
  </v-main>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, nextTick, useTemplateRef } from 'vue'
import { useRoute } from 'vue-router'
import DOMPurify from 'dompurify'
import { getMessages, createMessage, type Message } from '@/services/message.service'

// 类型定义
import type { BlogData, TocItem } from '@/models/blog.model'
// 响应式数据
const route = useRoute()
const blogId = ref(route.params.id)

const blogData = ref<BlogData>({
  id: '',
  title: '',
  subtitle: '',
  content: '',
  author: '',
  publishDate: '',
  readTime: 0,
  views: 0,
  tags: [],
  coverImage: ''
})

// 用户状态
const isLoggedIn = ref(false)
const currentUser = ref<{ name: string; email: string } | null>(null)

// 评论相关数据
const comments = ref<Message[]>([])
const commentForm = ref({
  name: '',
  email: '',
  content: ''
})

const loading = ref(true)
const error = ref('')
const readingProgress = ref(0)
const showSidebar = ref(true)
const showFab = ref(false)
const bottomNav = ref('')
const isLiked = ref(false)
const toc = ref<TocItem[]>([])
const activeHeading = ref('')

// 计算属性
const blogMeta = computed(() => [
  { icon: 'mdi-account', text: blogData.value.author },
  { icon: 'mdi-calendar', text: formatDate(blogData.value.publishDate) },
  { icon: 'mdi-clock-outline', text: `${blogData.value.readTime} 分钟阅读` },
  { icon: 'mdi-eye', text: `${blogData.value.views} 次浏览` }
])

const sanitizedContent = computed(() => {
  if (!blogData.value.content) return ''

  // 配置 DOMPurify 以允许安全的 HTML 标签
  const config = {
    ALLOWED_TAGS: [
      'h1',
      'h2',
      'h3',
      'h4',
      'h5',
      'h6',
      'p',
      'br',
      'strong',
      'em',
      'u',
      's',
      'ul',
      'ol',
      'li',
      'blockquote',
      'a',
      'img',
      'code',
      'pre',
      'table',
      'thead',
      'tbody',
      'tr',
      'th',
      'td',
      'div',
      'span',
      'section',
      'article'
    ],
    ALLOWED_ATTR: [
      'href',
      'src',
      'alt',
      'title',
      'class',
      'id',
      'target',
      'rel',
      'width',
      'height'
    ],
    ALLOW_DATA_ATTR: false,
    ALLOW_UNKNOWN_PROTOCOLS: false
  }

  return DOMPurify.sanitize(blogData.value.content, config)
})

// 方法
const loadComments = async () => {
  try {
    const res = await getMessages({ page: 1, pageSize: 10 })
    comments.value = res.list
  } catch (err) {
    console.error('加载评论失败:', err)
  }
}

const submitComment = async () => {
  try {
    // 检查是否登录
    if (!isLoggedIn.value) {
      alert('请先登录后再发表评论')
      return
    }

    if (!commentForm.value.content) {
      return
    }

    const newComment = await createMessage({
      name: currentUser.value?.name || '匿名用户',
      email: currentUser.value?.email || '',
      content: commentForm.value.content
    })

    comments.value = [newComment, ...comments.value]
    commentForm.value = { name: '', email: '', content: '' }
  } catch (err) {
    console.error('提交评论失败:', err)
  }
}

const loadBlog = async () => {
  try {
    loading.value = true
    error.value = ''

    // 模拟 API 调用
    await new Promise((resolve) => setTimeout(resolve, 1000))

    // 模拟博客数据
    blogData.value = {
      id: blogId.value as string,
      title: 'Vue 3 + TypeScript + Vite 现代化前端开发指南',
      subtitle: '深入探讨如何构建高效、可维护的现代化前端应用',
      content: `
        <h1>Vue 3 + TypeScript + Vite 现代化前端开发指南</h1>

        <h2>前言</h2>
        <p>在当今快速发展的前端技术栈中，Vue 3、TypeScript 和 Vite 的组合已经成为现代前端开发的主流选择。本文将深入探讨如何构建一个高效、可维护的现代化前端应用。</p>

        <h2>技术栈介绍</h2>

        <h3>Vue 3 核心特性</h3>
        <p>Vue 3 带来了许多令人兴奋的新特性：</p>
        <ul>
          <li><strong>组合式 API (Composition API)</strong>: 提供更好的逻辑复用和代码组织</li>
          <li><strong>更好的 TypeScript 支持</strong>: 原生支持 TypeScript，提供更好的类型推断</li>
          <li><strong>性能提升</strong>: 更小的包体积，更快的渲染速度</li>
          <li><strong>Tree-shaking 友好</strong>: 支持按需引入，减少最终打包体积</li>
        </ul>

        <blockquote>
          <p>Vue 3 的组合式 API 让我们能够更好地组织代码逻辑，提高代码的可读性和可维护性。</p>
        </blockquote>

        <h3>TypeScript 的优势</h3>
        <p>TypeScript 为 JavaScript 添加了静态类型检查，带来以下好处：</p>
        <ol>
          <li><strong>类型安全</strong>: 在编译时发现潜在错误</li>
          <li><strong>更好的 IDE 支持</strong>: 智能提示、自动补全、重构支持</li>
          <li><strong>代码可读性</strong>: 类型注解使代码意图更清晰</li>
          <li><strong>团队协作</strong>: 减少沟通成本，提高代码质量</li>
        </ol>

        <h3>代码示例</h3>
        <pre><code>// 组合式 API 示例
import { ref, computed, onMounted } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const doubleCount = computed(() => count.value * 2)

    onMounted(() => {
      console.log('组件已挂载')
    })

    return {
      count,
      doubleCount
    }
  }
}</code></pre>

        <h2>项目搭建</h2>

        <h3>1. 创建项目</h3>
        <pre><code># 使用 Vite 创建 Vue + TypeScript 项目
npm create vue@latest my-project
cd my-project
npm install</code></pre>

        <h3>2. 项目结构</h3>
        <pre><code>src/
├── components/          # 组件目录
│   ├── common/         # 通用组件
│   └── business/       # 业务组件
├── views/              # 页面组件
├── router/             # 路由配置
├── store/              # 状态管理
├── services/           # API 服务
├── utils/              # 工具函数
├── types/              # 类型定义
└── assets/             # 静态资源</code></pre>

        <h2>开发实践</h2>

        <h3>1. 组件设计原则</h3>
        <p>每个组件应该只负责一个功能，保持组件的简洁和可维护性。</p>

        <h3>2. 状态管理</h3>
        <p>使用 Pinia 进行状态管理，提供更好的 TypeScript 支持和开发体验。</p>

        <h2>性能优化</h2>

        <h3>1. 代码分割</h3>
        <p>通过路由级别的代码分割和组件懒加载来优化首屏加载时间。</p>

        <h3>2. 虚拟滚动</h3>
        <p>对于大量数据的列表，使用虚拟滚动来提升性能。</p>

        <h2>测试策略</h2>

        <h3>1. 单元测试</h3>
        <p>使用 Vitest 进行单元测试，确保组件功能的正确性。</p>

        <h3>2. 端到端测试</h3>
        <p>使用 Playwright 进行端到端测试，确保整个应用流程的正确性。</p>

        <h2>总结</h2>
        <p>Vue 3 + TypeScript + Vite 的组合为现代前端开发提供了强大的工具链。通过合理的项目结构、最佳实践和性能优化，我们可以构建出高质量、可维护的前端应用。</p>

        <p>关键要点：</p>
        <ul>
          <li>充分利用组合式 API 的优势进行逻辑复用</li>
          <li>严格使用 TypeScript 提升代码质量</li>
          <li>合理规划项目结构便于团队协作</li>
          <li>重视性能优化提升用户体验</li>
          <li>建立完善的测试体系保证代码质量</li>
        </ul>

        <p>希望这篇文章能帮助你在现代前端开发的道路上更进一步！</p>
      `,
      author: '前端开发工程师',
      publishDate: '2024-01-20',
      readTime: 15,
      views: 1234,
      tags: ['Vue 3', 'TypeScript', 'Vite', '前端开发', 'JavaScript'],
      coverImage: 'https://picsum.photos/1200/400?random=1',
      prevPost: {
        id: '1',
        title: 'Vue 3 组合式API深度解析'
      },
      nextPost: {
        id: '3',
        title: '现代前端工程化实践'
      }
    }

    // 等待 DOM 更新后生成目录
    await nextTick()
    generateToc()
  } catch (err) {
    error.value = '加载博客失败，请稍后重试'
    console.error('Error loading blog:', err)
  } finally {
    loading.value = false
  }
}

const generateToc = () => {
  const content = document.querySelector('.blog-content')
  if (!content) return

  const headings = content.querySelectorAll('h1, h2, h3, h4, h5, h6')
  toc.value = Array.from(headings).map((heading, index) => {
    const id = heading.id || `heading-${index}`
    heading.id = id
    return {
      id,
      text: heading.textContent || '',
      level: parseInt(heading.tagName.charAt(1))
    }
  })
}

const scrollToHeading = (id: string) => {
  const element = document.getElementById(id)
  if (element) {
    element.scrollIntoView({ behavior: 'smooth', block: 'start' })
  }
}

const blogContent = useTemplateRef('blog-content')
const scrollToTop = () => {
  if (blogContent.value) {
    blogContent.value.$el.scrollTo({ top: 0, behavior: 'smooth' })
  }
}

const toggleSidebar = () => {
  showSidebar.value = !showSidebar.value
}

const shareBlog = () => {
  if (navigator.share) {
    navigator.share({
      title: blogData.value.title,
      text: blogData.value.subtitle,
      url: window.location.href
    })
  } else {
    // 复制链接到剪贴板
    navigator.clipboard.writeText(window.location.href)
    // 这里可以显示一个提示消息
  }
}

const toggleLike = () => {
  isLiked.value = !isLiked.value
  // 这里可以调用 API 更新点赞状态
}

const updateReadingProgress = () => {
  const scrollTop = window.pageYOffset
  const docHeight = document.documentElement.scrollHeight - window.innerHeight
  const progress = (scrollTop / docHeight) * 100
  readingProgress.value = Math.min(100, Math.max(0, progress))

  // 控制浮动按钮显示
  showFab.value = scrollTop > 300
}

const updateActiveHeading = () => {
  const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6')
  let current = ''
  let minDistance = Infinity

  headings.forEach((heading) => {
    const rect = heading.getBoundingClientRect()
    const distance = Math.abs(rect.top - 150) // 距离顶部150px的位置

    if (rect.top <= 200 && distance < minDistance) {
      minDistance = distance
      current = heading.id
    }
  })

  activeHeading.value = current
}

const formatDate = (dateString: string) => {
  const date = new Date(dateString)
  return date.toLocaleDateString('zh-CN', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  })
}

const checkLoginStatus = async () => {
  // 这里应该调用实际的登录状态检查API
  // 模拟已登录状态
  isLoggedIn.value = true
  currentUser.value = {
    name: '当前用户',
    email: 'user@example.com'
  }
}

// 生命周期
onMounted(() => {
  loadBlog()
  loadComments()
  checkLoginStatus()
  window.addEventListener('scroll', updateReadingProgress)
  window.addEventListener('scroll', updateActiveHeading)
})

onUnmounted(() => {
  window.removeEventListener('scroll', updateReadingProgress)
  window.removeEventListener('scroll', updateActiveHeading)
})
</script>
